package com.atguigu.gmall.secKill.task;

import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.secKill.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.secKill.util.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @Author ZengMing
 * @Date 2021/7/14 19:37
 * @Description:秒杀商品存入缓存的定时任务
 */
@Component //定时任务需要交给spring容器管理
public class SecKillTask {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 秒杀商品存入redis缓存的定时任务
     */
    @Scheduled(cron = "0/15 * * * * *")
    public void seckillIntoRedisTask(){
        /**
         * 错误日志：BeanCreationException: Error creating bean with name 'secKillTask' defined in file [G:\200107\gmall\gmall-parent\service\service-activity\target\classes\com\atguigu\gmall\secKill\task\SecKillTask.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Need to invoke method 'seckillIntoRedisTask' found on proxy for target class 'SecKillTask' but cannot be delegated to target bean. Switch its visibility to package or protected.
         * 解决：public写成private私有去了
         */
        //计算时间段：DateUtil工具类里提供了计算五个时间段的方法
        List<Date> dateMenuList = DateUtil.getDateMenus();
        for (Date dateMenu : dateMenuList) {
            //定义查询条件的开始时间，数据库对应的开始时间格式为2021-7-14 20:00
            String startTime = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            //定义时间菜单的时间段时长
            Date date = DateUtil.addDateHour(dateMenu, 2);
            //定义查询条件的结束时间
            String endTime = DateUtil.data2str(date, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            //拼接查询条件
            LambdaQueryWrapper<SeckillGoods> wrapper = new LambdaQueryWrapper<>();
            //审核状态必须为通过（审核状态，0未审核，1审核通过，2审核不通过）
            wrapper.eq(SeckillGoods::getStatus,"1");
            //剩余库存大于0
            wrapper.gt(SeckillGoods::getStockCount,0);
            //  startTime=<开始时间 结束时间<endTime
            wrapper.ge(SeckillGoods::getStartTime,startTime);
            //这里应该是lt大于，但是数据库的数据设计的有问题，结束时间刚好为整点0分0秒，所以用le大于等于，方便查出数据
            wrapper.le(SeckillGoods::getEndTime,endTime);
            // 数据加入redis之前，redis中没有这个数据的（通过时间段key判断）
            /**
             * 错误日志：key设置错误，导致传参查询时查不出数据，得用没有下划线的常量
             */
            String key = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYYMMDDHH);
            //通过key判断，没有重合的key则存入redis中
            Set keys = redisTemplate.boundHashOps("SeckillGoods_" + key).keys();
            //参数校验
            if (keys != null && keys.size() > 0){
                wrapper.notIn(SeckillGoods::getId,keys);
            }
            //查询数据库符合查询时间段的数据
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(wrapper);
            //存入Redis: 格式：key:SeckillGoods_2021071414
            for (SeckillGoods seckillGood : seckillGoodsList) {
                redisTemplate.boundHashOps("SeckillGoods_" + key)
                        .put(seckillGood.getId(),seckillGood);
            }
        }

    }
}
